/*-------------------------------------------------------------------------
 *
 * syslogger.h
 *	  来自 postmaster/syslogger.c 的导出。
 *
 * Copyright (c) 2004-2022, PostgreSQL Global Development Group
 *
 * src/include/postmaster/syslogger.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef _SYSLOGGER_H
#define _SYSLOGGER_H

#include <limits.h>				/* 用于 PIPE_BUF */

#ifdef FDD
#include "port/fdb_crypt.h"

#define FDB_IS_AYDIT_ENCRYPT(type) (type == FDB_ENCRYPT_TYPE_XOR || type == FDB_ENCRYPT_TYPE_RC4)

#define FDB_PLAIN_AUDIT_LOG_HEAD_MD5STR ("fdb_mac")
#define FDB_DEFAULT_AUDIT_LOG_DIR "fdb_audit"
#define FDB_DEFAULT_AUDIT_LOG_ROTAT_AGE		(HOURS_PER_DAY * MINS_PER_HOUR)
#define FDB_DEFAULT_AUDIT_LOG_ROTAT_SIZE	(100 << 10)
#define FDB_DEFAULT_AUDIT_SEC_KEY "12345678"
#define FDB_DEFAULT_AUDIT_LOG_FILENAME_PREFIX "fdb_audit"
#define FDB_DEFAULT_AUDIT_LOG_ENCRYPT_TYPE	"xor"
#define FDB_AUDIT_LOG_FILENAME_FORMAT "_%Y-%m-%d_%H%M%S.audit"

#define FDB_ENABLE_AUDIT "fdb.enable_audit"
#define FDB_AUDIT_LOG_DIR "fdb.audit_log_directory"
#define FDB_AUDIT_LOG_FILENAME_PREFIX "fdb.audit_log_prefix"
#define FDB_AUDIT_LOG_ENCRYPT_KEY "fdb.audit_log_key"
#define FDB_AUDIT_LOG_AGE_INTERVAL "fdb.audit_log_rotation_age"
#define FDB_AUDIT_LOG_AGE_SIZE "fdb.audit_log_rotation_size"
#define FDB_AUDIT_LOG_ENCRYPT_TYPE "fdb.audit_log_encrypt"

int fdb_fillAuditLogEncodeState(struct fdb_cipher_state *pState, FDB_ENCRYPT_TYPE type, const unsigned char *key, int keyLen);
#endif //FDD
/*
 * 用于写入 syslogger 管道的原始协议结构。这里的想法是将长消息分割为不超过
 * PIPE_BUF 字节的块，根据 POSIX 规范，必须以原子方式写入管道。
 * 管道读取器随后使用协议头将消息的部分重新组合为一个字符串。
 * 读取器还可以处理非协议数据流入管道，尽管我们无法保证长字符串不会被拆分。
 *
 * 我们在 is_last 中使用非空字节，以使协议在稍微抵抗发现错误双空字节前奏方面更健壮。
 * 但是，除非我们小心，否则它仍然可能在 len 和/或 pid 字节中出现。
 */

#ifdef PIPE_BUF
/* 是否有 PIPE_BUF > 64K 的系统？不太可能，但... */
#if PIPE_BUF > 65536
#define PIPE_CHUNK_SIZE  65536
#else
#define PIPE_CHUNK_SIZE  ((int) PIPE_BUF)
#endif
#else							/* not defined */
/* POSIX规定PIPE_BUF的值必须至少为512，所以使用这个值 */
#define PIPE_CHUNK_SIZE  512
#endif

typedef struct
{
	char		nuls[2];		/* 总是 \0\0 */
	uint16		len;			/* 此块的大小（仅计算数据） */
	int32		pid;			/* 写入者的pid */
	bits8		flags;			/* PIPE_PROTO_* 的位掩码 */
	char		data[FLEXIBLE_ARRAY_MEMBER];	/* 数据负载从这里开始 */
} PipeProtoHeader;

typedef union
{
	PipeProtoHeader proto;
	char		filler[PIPE_CHUNK_SIZE];
} PipeProtoChunk;

#define PIPE_HEADER_SIZE  offsetof(PipeProtoHeader, data)
#define PIPE_MAX_PAYLOAD  ((int) (PIPE_CHUNK_SIZE - PIPE_HEADER_SIZE))

/* PipeProtoHeader->flags 的标志位 */
#define PIPE_PROTO_IS_LAST	0x01	/* 消息的最后一块？ */
/* 日志目标 */
#define PIPE_PROTO_DEST_STDERR	0x10
#define PIPE_PROTO_DEST_CSVLOG	0x20
#define PIPE_PROTO_DEST_JSONLOG	0x40

#ifdef FDD
#define PIPE_PROTO_DEST_AUDIT	0x80
#endif

/* GUC 选项 */
extern PGDLLIMPORT bool Logging_collector;
extern PGDLLIMPORT int Log_RotationAge;
extern PGDLLIMPORT int Log_RotationSize;
extern PGDLLIMPORT char *Log_directory;
extern PGDLLIMPORT char *Log_filename;
extern PGDLLIMPORT bool Log_truncate_on_rotation;
extern PGDLLIMPORT int Log_file_mode;

#ifndef WIN32
extern PGDLLIMPORT int syslogPipe[2];
#else
extern PGDLLIMPORT HANDLE syslogPipe[2];
#endif


extern int	SysLogger_Start(void);

extern void write_syslogger_file(const char *buffer, int count, int dest);

#ifdef EXEC_BACKEND
extern void SysLoggerMain(int argc, char *argv[]) pg_attribute_noreturn();
#endif

extern bool CheckLogrotateSignal(void);
extern void RemoveLogrotateSignalFiles(void);

/*
 * 保存关于当前被syslogger使用的日志文件的元数据
 * 文件的名称
 */
#define LOG_METAINFO_DATAFILE  "current_logfiles"
#define LOG_METAINFO_DATAFILE_TMP  LOG_METAINFO_DATAFILE ".tmp"

#endif							/* _SYSLOGGER_H */
